package com.hbzhit.common.utils;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.afterturn.easypoi.exception.excel.ExcelImportException;
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hbzhit.common.entity.ExcelVerifyEntity;
import com.hbzhit.common.exception.RRException;
import com.hbzhit.common.validator.group.ImportGroup;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;

/**
 * POI工具类
 * @date 2019-07-08
 * @author DING
 */
public class PoiUtils {

    /**
     * Workbook对象转为InputStream输入流
     * @param workbook Workbook对象
     */
    public static InputStream toInputStream(Workbook workbook) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        workbook.write(bos);
        byte[] barray = bos.toByteArray();
        return new ByteArrayInputStream(barray);
    }

    /**
     * Workbook对象导出为ResponseEntity对象
     * @param workbook Workbook对象
     * @param name 文件名
     */
    public static ResponseEntity<byte[]> export(Workbook workbook, String name) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.set("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name,"utf-8"));
        return new ResponseEntity<>(IoUtil.readBytes(toInputStream(workbook)), headers, HttpStatus.CREATED);
    }

    /**
     * Excel导入<br />默认一行标题，一行表头，开启注解校验，无自定义校验
     * @param is 输入流对象
     * @param c 类
     */
    public static <T> ExcelImportResult<T> importExcel(InputStream is, Class<?> c) throws Exception {
        return importExcel(is, c, 1, 1, true, null);
    }

    /**
     * Excel导入<br />默认一行标题，一行表头，开启注解校验，开启自定义校验
     * @param is 输入流对象
     * @param c 类
     * @param verifyHandler 自定义校验
     */
    public static <T> ExcelImportResult<T> importExcel(InputStream is, Class<?> c, IExcelVerifyHandler<T> verifyHandler) throws Exception {
        return importExcel(is, c, 1, 1, true, verifyHandler);
    }

    /**
     * Excel导入
     * @param is 输入流对象
     * @param c 类
     * @param titleRows 标题行数
     * @param headRows 表头行数
     * @param needVerify 是否需要校验数据有效性（实体注解校验）
     * @param verifyHandler 自定义校验规则
     */
    public static <T> ExcelImportResult<T> importExcel(InputStream is, Class<?> c, int titleRows, int headRows, boolean needVerify, IExcelVerifyHandler<T>  verifyHandler) throws Exception {
        /*导入参数*/
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headRows);
        if (needVerify) {
            params.setNeedVerify(true);
            params.setVerifyGroup(new Class[]{ImportGroup.class});
        }
        if (verifyHandler != null) {
            params.setVerifyHandler(verifyHandler);
        }

        /*执行导入*/
        ExcelImportResult<T> result;
        try {
            result = ExcelImportUtil.importExcelMore(is, c, params);
        } catch (ExcelImportException e) {
            throw new RRException(e.getMessage());
        }

        /*校验数据失败*/
        if (needVerify && result.isVerifyFail()) {
            JSONArray errs = new JSONArray();
            result.getFailList().forEach(entity -> {
                if (entity instanceof ExcelVerifyEntity) {
                    ExcelVerifyEntity verifyEntity = (ExcelVerifyEntity) entity;
                    JSONObject err = new JSONObject();
                    err.put("rowNum", verifyEntity.getRowNum());
                    err.put("errMsg", verifyEntity.getErrorMsg());
                    errs.add(err);
                }
            });
            throw new RRException("导入失败，请修改模板重新导入", errs);
        }
        if (CollUtil.isEmpty(result.getList())) {
            throw new RRException("导入失败，导入的数据为空");
        }

        return result;
    }
}
